import { AppTask } from "../app.task.class";
import { BehaviorSubject, Subject } from "rxjs";
import mqtt from "mqtt";
import { appConfig } from "../../configs/env.config.load";
import { logger } from "../../configs/log.config";
import { cond, curry, equals } from "ramda";
import { SrAlertMessageServer } from "./publish/sr.alert.message.server";
import { V3proSubjectMessage } from "../v3pro-task/model/v3pro.model";

/**
 * 与Starriver相关任务
 */
export class StarriverServer extends AppTask {
  // mqtt change subject
  // 用户在 mqtt 重连改变后触发新的 mqtt 对象的推送
  private __mqttChangeSubject = new BehaviorSubject<mqtt.MqttClient | undefined>(undefined);

  /**
   * starriver 错误发布订阅器
   * @private
   */
  constructor(private __srAlertMessagePublishSubject: Subject<V3proSubjectMessage>) {
    super();
  }

  /**
   * 暂停运行
   */
  async __pause(): Promise<boolean> {
    return true;
  }

  async __restore(): Promise<boolean> {
    return true;
  }

  /**
   * 运行
   */
  async __run(): Promise<void> {
    this.__connectMqtt();
    new SrAlertMessageServer(this.__mqttChangeSubject, this.__srAlertMessagePublishSubject)
      .start()
      .then();
    // timer(1000).subscribe(this.__addHealthTask);
    logger.info("starriver task started");
    await this.__await();
  }

  /**
   * 停止
   */
  async __stop(): Promise<boolean> {
    return Promise.resolve(true);
  }

  /**
   * mqtt 事件处理
   * @private
   */
  private __mqttEventHandler = curry(
    (mqttClient: mqtt.MqttClient, event: "connect" | "error" | "close", err?: Error) => {
      cond([
        [equals("connect"), () => logger.info("mqtt connected")],
        [equals("error"), () => logger.error("mqtt error 10s 后重连", err)],
        [equals("close"), () => logger.error("mqtt close, 10s 后重连")],
      ])(event);
      this.__mqttChangeSubject.next(equals("connect", event) ? mqttClient : undefined);
    },
  );

  /**
   * 连接mqtt
   */
  private __connectMqtt = () => {
    logger.info("connecting mqtt", appConfig.starriver.mqtt.address);
    const mqttClient = mqtt.connect(appConfig.starriver.mqtt.address, {
      reconnectPeriod: 10_000,
      username: appConfig.starriver.mqtt.username,
      password: appConfig.starriver.mqtt.password,
      keepalive: 60,
      rejectUnauthorized: false, // 忽略证书验证
    });
    const handler = this.__mqttEventHandler(mqttClient);
    mqttClient.on("connect", handler("connect"));
    mqttClient.on("error", handler("error"));
    mqttClient.on("close", handler("close"));
  };
}
